/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <rom.prevot@gmail.com> wrote this file. As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return R. Prevot
 * ----------------------------------------------------------------------------
 */

/******************************************************************************\
 *          ____                _______    _____ _             _              *
 *         |  _ \              |__   __|  / ____| |           | |             *
 *         | |_) | ___  _ __ _ __ | | ___| (___ | |_ ___   ___| | __          *
 *         |  _ < / _ \| '__| '_ \| |/ _ \\___ \| __/ _ \ / __| |/ /          *
 *         | |_) | (_) | |  | | | | | (_) |___) | || (_) | (__|   <           *
 *         |____/ \___/|_|  |_| |_|_|\___/_____/ \__\___/ \___|_|\_\          *
 *                                                                            *
\******************************************************************************/

package app.controllers;

import app.Tools;
import app.events.eventobjects.DataChangedEvent;
import app.events.DataChangedListener;
import app.core.UpdatedComp;
import app.events.CategorieChangedListener;
import app.events.ReferenceListener;
import app.events.eventobjects.CategorieAddedEvent;
import app.events.eventobjects.ReferenceAddedEvent;
import app.events.eventobjects.ReferenceDeletedEvent;
import app.events.eventobjects.ReferenceUpdatedEvent;
import app.exceptions.ReferenceOutOfStockException;
import app.models.Categorie;
import app.models.Factory;
import app.models.Reference;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.EventListenerList;

/**
 *
 * @author PREVROMA
 */
public class Catalogue {
    
    List<Reference> references;
    List<Categorie> categories;
    
    private EventListenerList listenerList = new EventListenerList();

    public Catalogue() {
        references = new ArrayList<Reference>();
        categories = new ArrayList<Categorie>();
    }
    
    /**
     * Charge toute les données
     * @todo faire un event pour le chargement complet
     * @param comp 
     */
    public void load(UpdatedComp comp){
        comp.setMax(-1);
        List l = Factory.getContext().createNamedQuery("Reference.findAll").getResultList();
        comp.setMax(l.size());
        int i = 0;
        for(Object o : l )
        {
            //maj du composant de mise a jour
            comp.setCurrent(i++);
            //récupération de la reference
            Reference ref = (Reference)o;
            addReference(ref);
        }
    }
        
    public void addReference(Reference ref){
        Categorie cat = ref.getCategorie();
        if(!categories.contains(cat)){
            categories.add(cat);
        }
        
        //si la référence existe déja, on récupère l'ancienne et on lui ajoute
        // la nouvelle qte en stock
        if(references.contains(ref)){
            Reference oldRef = ref;
            
            int newQte = ref.getStock();
            ref = references.get(references.indexOf(ref));
            ref.setStock(ref.getStock() + newQte);
            Factory.save(ref);
            
            fireReferenceUpdated(oldRef, ref);
        } else {
            references.add(ref);
            Factory.save(ref);
            fireReferenceAdded(ref);
        }
              
     }
    
    public void removeReference(Reference ref){
        Factory.remove(ref);
        references.remove(ref);
        fireReferenceDeleted(ref);
    }
    
    /**
     * @todo vérifier qu'il n'y a pas de double ajout et que le equals marche bien
     * @param oldRef
     * @param newRef 
     */
    public void updateReference(Reference oldRef, Reference newRef){
        
        Reference dbRef = Factory.getContext().find(Reference.class, oldRef.getId());
        dbRef.setCategorie(newRef.getCategorie());
        dbRef.setDesignation(newRef.getDesignation());
        dbRef.setPxAchatHT(newRef.getPxAchatHT());
        dbRef.setPxVenteTTC(newRef.getPxVenteTTC());
        dbRef.setStock(newRef.getStock());
        dbRef.setVendu(newRef.getVendu());
        Factory.save(dbRef);
        
        references.set(references.indexOf(oldRef), dbRef);
        
        fireReferenceUpdated(oldRef, dbRef);
    }
    
    /**
     * Sort une qte de reférence du stock
     */
    public void pickReference(Reference ref, int qte) throws ReferenceOutOfStockException{
        
        int nbStock = ref.getStock();
        if(qte > nbStock){
            throw new ReferenceOutOfStockException(ref);
        }
        Reference oldRef = ref;
        ref.setStock(nbStock - qte);
        fireReferenceUpdated(oldRef, ref);
    }
   

    public List<Reference> getReferences() {
        return this.references;
    }
    
    public List<Categorie> getCategories(){
        return this.categories;
    }
        
    
    
    // -- Accesseurs listeners ---------------------------------------------- //
    public void addReferenceListener(ReferenceListener l){
        listenerList.add(ReferenceListener.class, l);
    }
    public void removeReferenceListener(ReferenceListener l){
        listenerList.remove(ReferenceListener.class, l);
    }
      
    /**
     * 
     * @deprecated use addReferenceListener instead
     * @param listener 
     */
    public void addReferenceChangedListener(ReferenceListener listener){
        listenerList.add(ReferenceListener.class, listener);
    }
    /**
     * @deprecated use removeReferenceListener instead
     * @param listener 
     */
    public void removeReferenceChangedListener(ReferenceListener listener){
        listenerList.remove(ReferenceListener.class, listener);
    }
    
    // -- Lancement d'evenements -------------------------------------------- //
    
    public void fireReferenceAdded(Reference ref){
        Object[] listeners = listenerList.getListenerList();
        // Each listener occupies two elements - the first is the listener class
        // and the second is the listener instance
        for (int i=0; i < listeners.length; i+=2) {
            if (listeners[i] == ReferenceListener.class) {
                ((ReferenceListener)listeners[i+1]).onReferenceAdded(new ReferenceAddedEvent(ref, this));
            }
        }
    }
    
    public void fireReferenceUpdated(Reference oldRef, Reference newRef){
        Object[] listeners = listenerList.getListenerList();
        // Each listener occupies two elements - the first is the listener class
        // and the second is the listener instance
        for (int i=0; i < listeners.length; i+=2) {
            if (listeners[i] == ReferenceListener.class) {
                ((ReferenceListener)listeners[i+1]).onReferenceUpdated(new ReferenceUpdatedEvent(oldRef, newRef, this));
            }
        }
    }
    
    public void fireReferenceDeleted(Reference ref){
        Object[] listeners = listenerList.getListenerList();
        // Each listener occupies two elements - the first is the listener class
        // and the second is the listener instance
        for (int i=0; i < listeners.length; i+=2) {
            if (listeners[i] == ReferenceListener.class) {
                ((ReferenceListener)listeners[i+1]).onReferenceDeleted(new ReferenceDeletedEvent(ref, this));
            }
        }
    }
    
}
